/*++

Copyright (c) 2007  Microsoft Corporation 

Filename: 

    WMIServices.cs

Abstract: 

    A class that uses WMI to get the data.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
using System.Data;
using System.Windows.Forms;
using System.Globalization;

namespace NRTMAddIn
{
    class WMIServices
    {
        #region Variables
        private Document nrtmDocument;
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the NRTM Document object that this dialog is loaded for.
        /// </summary>
        internal Document NRTMDocument
        {          
            set { nrtmDocument = value; }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Get WMI scope for serverName
        /// </summary>
        /// <param name="ServerName">Server to get scope</param>
        /// <param name="errMsg">Out error message in case of failure</param>
        /// <returns></returns>
        internal static ManagementScope GetWMIScope(string ServerName, ref string errMsg)
        {
            // Configure the connection settings.
            ConnectionOptions options = new ConnectionOptions();
            options.Impersonation = ImpersonationLevel.Impersonate;
            //options.Timeout = TimeSpan.FromSeconds(5);
            ManagementPath path = new ManagementPath(String.Format(CultureInfo.InvariantCulture,"\\\\{0}\\root\\cimv2", ServerName));
            ManagementScope scope = new ManagementScope(path, options);

            // Try and connect to the remote (or local) machine.
            try
            {
                scope.Connect();
                return scope;
            }
            catch (ManagementException ex)
            {
                // Failed to authenticate properly.
                //MessageBox.Show("Failed to authenticate on " + ServerName + " : " + ex.Message);
                errMsg = ex.Message;
                return null;
            }
            catch (System.Runtime.InteropServices.COMException ex)
            {
                // Unable to connect to the RPC service on the remote machine.
                //MessageBox.Show("Unable to connect to RPC service on " + ServerName + " : " + ex.Message);
                errMsg = ex.Message;
                return null;
            }
            catch (System.UnauthorizedAccessException ex)
            {
                // User not authorized.
                //MessageBox.Show("Unauthorized access to " + ServerName + " : " + ex.Message);
                errMsg = ex.Message;
                return null;
            }
        }

        /// <summary>
        /// Get logical disk details
        /// </summary>
        /// <param name="scope">Server scope</param>
        /// <param name="ServerName">Server name</param>
        public bool GetLogicalDrives(ManagementScope scope, string ServerName)
        {
            long MB = 1048576; //megabyte in # of bytes 1024x1024

            DataRow drDiskDtails = null;

            try
            {
                ManagementObjectSearcher moSearch = new ManagementObjectSearcher(scope,
                    new ObjectQuery(Global.GetResourceString("WMI_GetDiskDetails_Query")));
                ManagementObjectCollection moReturn = moSearch.Get();

                if (moReturn == null)
                {
                    return false;
                }

                foreach (ManagementObject mo in moReturn)
                {
                    //variables for numerical conversions
                    double fs = 0;
                    double tot = 0;
                    double fp = 0;

                    drDiskDtails = nrtmDocument.MonitorDB.DtDiskDetails.NewRow();
                    drDiskDtails["ServerName"] = ServerName;
                    
                    if (mo["DeviceID"] != null)
                    {
                        drDiskDtails["DiskName"] = mo["DeviceID"].ToString();
                    }
                    else
                    {
                        drDiskDtails["DiskName"] = DBNull.Value;
                    }

                    //Total space in MB
                    if (mo["Size"] != null)
                    {
                        tot = Convert.ToInt64(mo["Size"], CultureInfo.InvariantCulture) / MB;
                        drDiskDtails["TotalSizeMB"] = tot;
                    }
                    else
                    {
                        drDiskDtails["TotalSizeMB"] = DBNull.Value;
                    }

                    //Free space in MB
                    if (mo["FreeSpace"] != null)
                    {
                        fs = Convert.ToInt64(mo["FreeSpace"], CultureInfo.InvariantCulture) / MB;
                        drDiskDtails["FreeSpaceMB"] = fs;
                    }
                    else
                    {
                        drDiskDtails["FreeSpaceMB"] = DBNull.Value;
                    }

                    if (mo["FileSystem"] != null)
                    {
                        drDiskDtails["FileSystem"] = mo["FileSystem"].ToString();
                    }
                    else
                    {
                        drDiskDtails["FileSystem"] = DBNull.Value;
                    }

                    if (mo["Description"] != null)
                    {
                        drDiskDtails["Description"] = mo["Description"].ToString();
                    }
                    else
                    {
                        drDiskDtails["Description"] = DBNull.Value;
                    }

                    //free percentage
                    if (mo["FreeSpace"] != null
                        || mo["Size"] != null)
                    {
                        fp = fs / tot * 100;
                        drDiskDtails["PerFreeSpace"] = fp;
                        //Disk state based on threshold values
                        drDiskDtails["DiskState"] = Global.GetDiskState(Convert.ToInt32(fp, CultureInfo.InvariantCulture));
                    }
                    else
                    {
                        drDiskDtails["PerFreeSpace"] = DBNull.Value;
                        drDiskDtails["DiskState"] = Global.GetResourceString("StatusDlg_Update_Unavail");
                    }


                    nrtmDocument.MonitorDB.DtDiskDetails.Rows.Add(drDiskDtails);
                }

                return true;
            }
            catch (System.Threading.ThreadAbortException)
            {
                //Ignore thread abort exception
                return false;
            }
            catch (NrtmException ex)
            {
                //Exception from sub function. Pass on to entry point
                throw new NrtmException("Get disk details", ex.InnerException);
            }
            catch (Exception ex)
            {
                //Exception from current function
                throw new NrtmException("Get disk details", ex);
            }
        }

        /// <summary>
        /// Get the IP address from the server name
        /// </summary>
        /// <param name="scope">Server scope</param>
        /// <returns>IP address</returns>
        internal static string GetNetworkAddresses(ManagementScope scope)
        {
            ManagementObjectCollection adapters;
            ManagementObjectSearcher search;

            string ipAddress = "";

            try
            {
                search = new ManagementObjectSearcher(scope, new ObjectQuery(Global.GetResourceString("WMI_GetIPAddress_Query")));
                adapters = search.Get();

                foreach (ManagementObject adapter in adapters)
                {
                    if (adapter["IPAddress"] != null)
                    {
                        //Store the first IP address for the current server
                        ipAddress = (((string[])adapter.Properties["IPAddress"].Value)[0]);
                    }
                    //One one entry will exist for given scope
                    break;
                }

                //Return the IP address
                return ipAddress;
            }
            catch (System.Threading.ThreadAbortException)
            {
                //Ignore thread abort exception
                return string.Empty;
            }
            catch (NrtmException ex)
            {
                //Exception from sub function. Pass on to entry point
                throw new NrtmException("Get network address", ex.InnerException);
            }
            catch (Exception ex)
            {
                //Exception from current function
                throw new NrtmException("Get network address", ex);
            }
        }

        /// <summary>
        /// Get the Server name from the IP address
        /// </summary>
        /// <param name="scope">Server scope</param>
        /// <returns>Server Name</returns>
        internal static string GetServerName(ManagementScope scope)
        {
            ManagementObjectCollection adapters;
            ManagementObjectSearcher search;

            string serverName = "";
            try
            {
                search = new ManagementObjectSearcher(scope, new ObjectQuery(Global.GetResourceString("WMI_GetServerName")));
                adapters = search.Get();

                foreach (ManagementObject adapter in adapters)
                {
                    if (adapter["CSName"] != null)
                    {
                        //Store the server name
                        serverName = adapter["CSName"].ToString();
                    }
                    //One one entry will exist for given scope
                    break;
                }

                //Return the server name
                return serverName;
            }
            catch (System.Threading.ThreadAbortException)
            {
                //Ignore thread abort exception
                return string.Empty;
            }
            catch (NrtmException ex)
            {
                //Exception from sub function. Pass on to entry point
                throw new NrtmException("Get Server Name", ex.InnerException);
            }
            catch (Exception ex)
            {
                //Exception from current function
                throw new NrtmException("Get Server Name", ex);
            }
        }
        #endregion
    }
}
